#ifndef INTERPRETER
#define INTERPRETER

#include"interpreter.hpp"

void interpreter::report(int line,std::string& msg){
	haveError=true;
	std::cout<<"[line "<<line<<"] Error: "<<msg<<"\n";
}

void interpreter::report(int line,const char* msg){
	haveError=true;
	std::cout<<"[line "<<line<<"] Error: "<<msg<<"\n";
}

interpreter::interpreter(decltype(tokens) tokenList){
	this->tokens=tokenList;
}

void interpreter::setTokens(decltype(tokens) tokenList){
	this->tokens=tokenList;
}

void interpreter::addStatement(statement* s){
	statements.push_back(s);
}

void interpreter::initStatement(parser* p){
	current=0;
	while(!atTail()){
		statements.push_back(getStatement(p));
	}
}

void interpreter::setGlobalEnvironment(){
	innerEnvironment=new environment;
}

statement* interpreter::getStatement(parser* p){
	if((*tokens)[current].getType()=="KEYWORD"){
		if((*tokens)[current].getLexeme()=="print"){
			return printStatement::readStatement(p,this);
		}
		if((*tokens)[current].getLexeme()=="var"){
			return declarationStatement::readStatement(p,this);
		}
	}
	else if((*tokens)[current].getType()=="LEFT_BRACE"){
		return blockStatement::readStatement(p,this);
	}
	else{
		return expressionStatement::readStatement(p,this);
	}
}

bool interpreter::atTail(){
	return current>=tokens->size();
}

void interpreter::next(){
	current++;
}

void interpreter::prev(){
	current--;
}

bool interpreter::meetSemicolon(){
	return (*tokens)[current].getType()=="SEMICOLON";
}

bool interpreter::meetEqual(){
	return (*tokens)[current].getType()=="EQUAL";
}

bool interpreter::meetRightBrace(){
	return (*tokens)[current].getType()=="RIGHT_BRACE";
}

int interpreter::getCurrent(){
	return current;
}

int interpreter::getCurrentLine(){
	return (*tokens)[current].getLine();
}

std::string interpreter::getCurrentLexeme(){
	return (*tokens)[current].getLexeme();
}

std::string interpreter::getCurrentType(){
	return (*tokens)[current].getType();
}

void interpreter::define(std::string& name,var* value){
	innerEnvironment->define(name,value);
}

void interpreter::enterEnvironment(){
	environment* tmp=innerEnvironment;
	innerEnvironment=new environment(tmp);
}

void interpreter::quitEnvironment(){
	environment* tmp=innerEnvironment;
	innerEnvironment=innerEnvironment->getFather();
	DELETE(tmp);
}

var* interpreter::find(std::string& name){
	environment* tmp=innerEnvironment;
	while(tmp!=nullptr){
		var* ans=tmp->find(name);
		if(ans!=nullptr)return ans;
		tmp=tmp->getFather();
	}
	return nullptr;
}

void interpreter::run(){
	for(auto it:statements){
		it->execute(this);
	}
}

#endif